home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_number / large_fraction.e < prev    next >
Text File  |  2000-03-25  |  11KB  |  412 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. class LARGE_FRACTION
  13. --
  14. -- To implement NUMBER (do not use this class, see NUMBER).
  15. --
  16.        
  17. inherit ABSTRACT_FRACTION;
  18.    
  19. creation make, make_simply
  20.    
  21. feature {NUMBER}
  22.    
  23.    is_negative: BOOLEAN;
  24.  
  25.    numerator: ABSTRACT_INTEGER; 
  26.     
  27.    denominator: ABSTRACT_INTEGER; 
  28.    
  29. feature {NUMBER}
  30.    
  31.    make (n, d: ABSTRACT_INTEGER; s: BOOLEAN) is 
  32.      -- create a simplified large_fraction
  33.       require
  34.      n.is_positive; 
  35.      d.is_positive;
  36.      not ((n \\ d) @= 0);  
  37.       local
  38.      gcd_frac,num,den: ABSTRACT_INTEGER;
  39.       do
  40.      gcd_frac := n.gcd(d);
  41.       num ?= n // gcd_frac; 
  42.      den ?= d // gcd_frac;      
  43.      numerator := num;
  44.      denominator := den; 
  45.      is_negative := s;
  46.       end;  
  47.  
  48.    make_simply (n, d: ABSTRACT_INTEGER; s: BOOLEAN)  is 
  49.      -- create a large_fraction without simplify it
  50.       require
  51.      n.is_positive; 
  52.      d.is_positive;
  53.      not ((n \\ d) @= 0);  
  54.       do
  55.      numerator := n;
  56.      denominator := d; 
  57.      is_negative := s;
  58.       end; 
  59.  
  60. feature
  61.  
  62.    infix "#<"(other: DOUBLE): BOOLEAN is  
  63.       do   
  64.      if (Current <= max_double) and then (min_double <= Current) then
  65.         Result := to_double < other;
  66.      else 
  67.         Result := max_double > Current;
  68.      end;
  69.       end;  
  70.    
  71.    is_positive: BOOLEAN is
  72.       do
  73.      Result := not is_negative;
  74.       end;
  75.    
  76.    append_in(string : STRING) is  
  77.       do   
  78.      if is_negative then
  79.         string.extend('-');
  80.      end;
  81.      numerator.append_in(string); 
  82.      string.extend('/'); 
  83.      denominator.append_in(string); 
  84.       end;  
  85.  
  86.    is_equal(other: like Current): BOOLEAN is  
  87.       do
  88.      if is_negative then
  89.         if other.is_negative then
  90.            Result := (denominator.is_equal(other.denominator) and then 
  91.               numerator.is_equal(other.numerator));
  92.         end;
  93.      elseif other.is_positive then
  94.         Result := (denominator.is_equal(other.denominator) and then 
  95.                numerator.is_equal(other.numerator));
  96.      end;
  97.       end;  
  98.    
  99. feature {NUMBER} -- To convert a LARGE_FRACTION  
  100.    
  101.    to_double: DOUBLE is 
  102.       require 
  103.      numerator.is_double;
  104.      denominator.is_double;
  105.       do        
  106.      Result := numerator.to_double / denominator.to_double;
  107.      if is_negative then
  108.         Result := - Result;
  109.      end;
  110.       end;
  111.    
  112. feature {NUMBER} -- Opposite    
  113.  
  114.    prefix "-": NUMBER is  
  115.      -- Opposite of 'Current'.  
  116.       do
  117.      !LARGE_FRACTION!Result.make_simply(numerator,denominator,not is_negative);
  118.       end;  
  119.    
  120.    
  121. feature {NUMBER} -- Addition 
  122.  
  123.    infix "+"(other: NUMBER): NUMBER is  
  124.       -- Sum of 'Current' and 'other'.  
  125.       do
  126.      Result := other.add_with_large_fraction(Current); 
  127.       end;  
  128.    
  129.    
  130.    add_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): NUMBER is  
  131.       local
  132.      num : ABSTRACT_INTEGER;
  133.       do   
  134.      if (is_negative) then
  135.         num ?= (other * denominator) + (-numerator);
  136.         check
  137.            num /= Void;
  138.         end;
  139.      else
  140.         num ?= (other * denominator) + numerator;
  141.         check
  142.            num /= Void;
  143.         end;        
  144.      end;
  145.      Result := from_two_abstract_integer(num,denominator);
  146.       end;  
  147.     
  148.    add_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): NUMBER is  
  149.       local
  150.      num: ABSTRACT_INTEGER;
  151.       do   
  152.      if is_negative then
  153.         num ?= (other * denominator) + (-numerator);
  154.         check
  155.            num /= Void;
  156.         end;
  157.      else
  158.         num ?= (other * denominator) + numerator;
  159.         check
  160.            num /= Void;
  161.         end;        
  162.      end;
  163.      Result := from_two_abstract_integer(num,denominator);     
  164.       end;  
  165.    
  166.    add_with_small_fraction(other: SMALL_FRACTION): NUMBER is  
  167.       do
  168.      Result := other.add_with_large_fraction(Current);
  169.       end;  
  170.    
  171.    
  172.    add_with_large_fraction(other: LARGE_FRACTION): NUMBER is  
  173.       local
  174.      new_num, new_den: ABSTRACT_INTEGER;
  175.       do
  176.      new_den ?= denominator * other.denominator;
  177.      if is_negative and then other.is_negative then
  178.         new_num ?= (-(numerator) * other.denominator) + (-(other.numerator) * denominator);
  179.      elseif is_negative then
  180.         new_num ?= (-(numerator) * other.denominator) + (other.numerator * denominator);
  181.      elseif other.is_negative then
  182.         new_num ?= (numerator * other.denominator) + (-(other.numerator) * denominator);
  183.      else
  184.         new_num ?= (numerator * other.denominator) + (other.numerator * denominator);
  185.      end;
  186.      check
  187.         new_num /= Void;
  188.         new_den /= Void;
  189.      end;
  190.      Result := from_two_abstract_integer(new_num,new_den);
  191.       end; 
  192.    
  193.    infix "@+"(other: INTEGER): NUMBER is  
  194.       -- Sum of 'Current' and 'other'.  
  195.       local
  196.      tmp: SMALL_INTEGER;
  197.       do
  198.      !SMALL_INTEGER!tmp.make(other);
  199.      Result := add_with_small_integer(tmp);
  200.       end;  
  201.  
  202.  
  203. feature {NUMBER} -- Multiplication  
  204.    
  205.    infix "*" (other: NUMBER): NUMBER is
  206.       do
  207.      Result := other.multiply_with_large_fraction(Current);
  208.       end;
  209.    
  210.    multiply_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): NUMBER is  
  211.       local
  212.      num: ABSTRACT_INTEGER;      
  213.       do   
  214.      num ?= numerator.multiply_with_large_positive_integer(other);
  215.      check
  216.         num /= Void;
  217.      end;     
  218.      if is_negative then
  219.         num ?= -num;
  220.         Result := from_two_abstract_integer(num,denominator);
  221.      else
  222.         Result := from_two_abstract_integer(num,denominator);        
  223.      end;
  224.       end;  
  225.     
  226.    multiply_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): NUMBER is  
  227.       local
  228.      num: ABSTRACT_INTEGER;
  229.       do   
  230.      num ?= numerator.multiply_with_large_negative_integer(other);
  231.      check
  232.         num /= Void;
  233.      end;
  234.      if is_negative then
  235.         num ?= -num;
  236.         Result := from_two_abstract_integer(num, denominator);
  237.      else
  238.         Result := from_two_abstract_integer(num, denominator);
  239.      end;
  240.       end;  
  241.     
  242.    multiply_with_small_fraction(other: SMALL_FRACTION): NUMBER is  
  243.       do   
  244.     Result := other.multiply_with_large_fraction(Current); 
  245.       end;  
  246.    
  247.    multiply_with_large_fraction (other: LARGE_FRACTION) : NUMBER is
  248.       local
  249.      prod1, prod2: ABSTRACT_INTEGER;
  250.       do
  251.      if (is_negative and then other.is_negative) or else (is_positive and then other.is_positive) then
  252.         prod1 ?= numerator * other.numerator;    
  253.      elseif is_negative then
  254.         prod1 ?= -numerator * other.numerator;
  255.      else
  256.         prod1 ?= numerator * -other.numerator;
  257.      end;
  258.      prod2 ?= denominator * other.denominator;    
  259.      check
  260.         prod1 /= Void;
  261.         prod2 /= Void;
  262.      end;
  263.      Result := from_two_abstract_integer(prod1,prod2);
  264.       end;
  265.    
  266.    infix "@*"(other: INTEGER): NUMBER is  
  267.       local  
  268.      tmp: SMALL_INTEGER; 
  269.       do 
  270.      if numerator.is_one then
  271.         if is_negative then
  272.            Result := from_integer_and_abstract_integer(-other,denominator);
  273.         else
  274.            Result := from_integer_and_abstract_integer(other,denominator);
  275.         end;
  276.      else
  277.         !SMALL_INTEGER!tmp.make(other); 
  278.         Result := multiply_with_small_integer(tmp); 
  279.      end;  
  280.       end;  
  281.       
  282.    infix "@/"(other: INTEGER): NUMBER is  
  283.       do 
  284.      if other = 1 then
  285.         Result := Current;
  286.      else
  287.         Result := Current * from_two_integer(1,other);
  288.      end;
  289.       end; 
  290.    
  291.    
  292. feature {NUMBER} -- Inverse   
  293.    
  294.    inverse: NUMBER is  
  295.       do   
  296.      if numerator.is_one then
  297.         Result := denominator;
  298.      elseif (-numerator).is_one then
  299.         Result := -denominator;
  300.      else
  301.         !LARGE_FRACTION!Result.make_simply(denominator, numerator, is_negative);
  302.      end;
  303.       end;  
  304.    
  305.    
  306. feature -- Comparisons with INTEGER
  307.    
  308.    infix "@<"(other: INTEGER): BOOLEAN is
  309.       do
  310.      Result := numerator < (denominator @* other);
  311.       end;
  312.    
  313.    infix "@>"(other: INTEGER): BOOLEAN is
  314.       do
  315.      Result := numerator > (denominator @* other);
  316.       end;
  317.    
  318.     infix "@<="(other: INTEGER): BOOLEAN is
  319.       do
  320.      Result := numerator <= (denominator @* other);
  321.       end;
  322.    
  323.     infix "@>="(other: INTEGER): BOOLEAN is
  324.       do
  325.      Result := numerator >= (denominator @* other);
  326.       
  327.       end;
  328.    
  329. feature -- Comparisons with NUMBER 
  330.    
  331.    infix "<"(other: NUMBER): BOOLEAN is  
  332.       do   
  333.      Result := other.greater_with_large_fraction(Current); 
  334.       end;  
  335.    
  336. feature -- Comparisons with DOUBLE
  337.    
  338.    infix "#=" (other: DOUBLE): BOOLEAN is
  339.       do
  340.      if (Current <= max_double) and then (min_double <= Current) then
  341.         Result := to_double = other;
  342.      end;
  343.       end;
  344.    
  345.    infix "#<=" (other: DOUBLE): BOOLEAN is
  346.       do
  347.       end
  348.      
  349.      
  350.    infix "#>=" (other: DOUBLE): BOOLEAN is    
  351.       do
  352.       end
  353.  
  354.    infix "#>" (other: DOUBLE): BOOLEAN is    
  355.       do
  356.       end
  357.    
  358.    
  359. feature{NUMBER}
  360.    
  361.   greater_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): BOOLEAN is  
  362.       do
  363.      if is_negative then
  364.         Result := denominator.multiply_with_large_positive_integer(other) < -numerator;
  365.      else
  366.         Result := denominator.multiply_with_large_positive_integer(other) < numerator;
  367.      end;
  368.       end;
  369.     
  370.    greater_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): BOOLEAN is
  371.       do
  372.      if is_negative then
  373.         Result := denominator.multiply_with_large_negative_integer(other) < -numerator;
  374.      else
  375.         Result := denominator.multiply_with_large_negative_integer(other) < numerator;
  376.      end;
  377.       end;
  378.     
  379.    greater_with_small_fraction(other: SMALL_FRACTION): BOOLEAN is  
  380.       do   
  381.      if is_negative then
  382.         Result := other.small_numerator * denominator < -numerator * other.small_denominator;
  383.      else
  384.         Result := other.small_numerator * denominator < numerator * other.small_denominator;
  385.      end;
  386.       end;  
  387.    
  388.    greater_with_large_fraction(other: LARGE_FRACTION): BOOLEAN is  
  389.       do   
  390.      if is_negative and then other.is_negative then
  391.         Result := numerator * other.denominator < other.numerator * denominator;
  392.      elseif is_negative then
  393.         Result := other.numerator * denominator < -numerator * other.denominator;
  394.      elseif other.is_negative then
  395.         Result := -other.numerator * denominator < numerator * other.denominator;
  396.      else
  397.         Result := other.numerator * denominator < numerator * other.denominator;
  398.      end;
  399.       end;     
  400.     
  401. invariant  
  402.     
  403.    not (numerator.is_integer and denominator.is_integer);
  404.  
  405. end -- LARGE_FRACTION
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.